import 'package:family_expense/features/bank_card/widgets/bank_shared.dart';
import 'package:family_expense/features/income_expense/constants/income_expense_type.dart';
import 'package:family_expense/features/income_expense/constants/payment_type.dart';
import 'package:family_expense/features/income_expense/models/income_expense_detail.dart';
import 'package:family_expense/features/income_expense_detail_type/models/income_expense_detail_type.dart';
import 'package:family_expense/features/income_expense_detail_type/services/income_expense_detail_type_loader.dart';
import 'package:flutter/material.dart';
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
import 'package:my_flutter_core/my_flutter_core.dart';
import 'package:scrollable_positioned_list/scrollable_positioned_list.dart';

class IncomeExpenseDetailShared {
  static const Color expenseAmountColor = Colors.green;

  /// Gets the [Icon] for different [type].
  static Widget? getTypeIcon(String? type, {double? size, Color? color}) {
    Icon? icon;

    switch (type) {
      case IncomeExpenseType.income:
        icon = Icon(
          MdiIcons.emoticonHappyOutline,
          color: color ?? Colors.green,
          size: size,
        );
        break;
      case IncomeExpenseType.expense:
        icon = Icon(
          MdiIcons.emoticonSadOutline,
          color: color ?? Colors.orange,
          size: size,
        );
        break;
      case PaymentType.cash:
        icon = Icon(MdiIcons.currencyCny, color: color, size: size);
        break;
      case PaymentType.creditCard:
        icon = Icon(Icons.credit_card, color: color, size: size);
        break;
    }

    return icon;
  }

  /// Gets the color based on input [amount].
  static Color? getAmountColor(dynamic amount) {
    return amount >= 0 ? Colors.red[400] : expenseAmountColor;
  }

  static String getPaymentTypeTitle(String? paymentType) {
    var title = '未定义';

    if (paymentType == PaymentType.cash) {
      title = '现金';
    } else if (paymentType == PaymentType.creditCard) {
      title = '信用卡';
    }

    return title;
  }

  /// Gets the type title for income or expense based on [incomeExpenseDetail.type].
  /// If this type has been deleted then itself will be returned instead.
  static String getIncomeOrExpenseTypeTitle(
    IncomeExpenseDetail incomeExpenseDetail,
  ) {
    return IncomeExpenseDetailTypeLoader.getIncomeExpenseDetailType(
          incomeExpenseDetail.type,
          incomeExpenseDetail.detailType,
        )?.title ??
        incomeExpenseDetail.detailType ??
        '';
  }

  /// Shows selection modal for different type selection, income/expense type, income type, expense type, payment type.
  /// [categories] is the data used to display with title and code.
  /// If [title] is not provided only [ListView] will be displayed.
  /// [currentType] used to highlight the item if the type matches.
  static void showTypeModalBottomSheet(
    BuildContext context,
    Map<String, String> categories,
    ValueChanged<String> onTap, {
    String? title,
    String? currentType,
    double? height,
  }) {
    // Converts the map to list tiles.
    final listTiles = categories.keys
        // Adds subtitle for expense type.
        .map(
          (p) => ListTile(
            leading: IncomeExpenseDetailShared.getTypeIcon(p),
            title: Text(categories[p]!),
            selected: p == currentType,
            onTap: () => onTap(p),
          ),
        )
        .toList();

    showModalBottomSheet<void>(
      context: context,
      builder: (context) {
        if (title.isNullOrEmpty) {
          return ListView(children: listTiles);
        } else {
          return SizedBox(
            height: height,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                const SizedBox(height: 15.0),
                Text(title!, style: const TextStyle(fontSize: 18.0)),
                const SizedBox(height: 10.0),
                Expanded(child: ListView(children: listTiles)),
              ],
            ),
          );
        }
      },
    );
  }

  /// Shows selection modal for different type selection, income/expense type, income type, expense type, payment type.
  /// [categories] is the data used to display with title and code.
  /// If [title] is not provided only [ListView] will be displayed.
  /// [currentType] used to highlight the item if the type matches.
  static void showIncomeExpenseDetailTypeModalBottomSheet(
    BuildContext context,
    List<IncomeExpenseDetailType> detailTypes,
    ValueChanged<String?> onTap, {
    String? title,
    String? currentType,
    double? height,
  }) {
    var initialScrollIndex = detailTypes.indexWhere(
      (element) => element.name == currentType,
    );

    if (initialScrollIndex < 0) {
      initialScrollIndex = 0;
    }

    final scollableList = ScrollablePositionedList.builder(
      itemCount: detailTypes.length,
      initialScrollIndex: detailTypes.length > 4 ? initialScrollIndex : 0,
      itemBuilder: (context, index) {
        final p = detailTypes[index];

        return p.subtitle.isNullOrEmpty
            ? ListTile(
                title: Text(p.title!),
                selected: p.name == currentType,
                onTap: () => onTap(p.name),
              )
            : ListTile(
                title: Text(p.title!),
                subtitle: Text(p.subtitle!),
                selected: p.name == currentType,
                onTap: () => onTap(p.name),
              );
      },
    );

    showModalBottomSheet<void>(
      context: context,
      builder: (context) {
        if (title.isNullOrEmpty) {
          return scollableList;
        } else {
          return SizedBox(
            height: height,
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                const SizedBox(height: 15.0),
                Text(title!, style: const TextStyle(fontSize: 18.0)),
                const SizedBox(height: 10.0),
                Expanded(child: scollableList),
              ],
            ),
          );
        }
      },
    );
  }

  /// Shows a pick modal for income/expense type selection.
  static void showIncomeExpenseTypeModalBottomSheet(
    BuildContext context,
    ValueChanged<String> onTap, {
    String? currentType,
  }) {
    showTypeModalBottomSheet(
      context,
      IncomeExpenseType.getCategories(),
      onTap,
      title: '支出/收入',
      currentType: currentType,
      height: 170.0,
    );
  }

  /// Shows a pick modal for income detail type selection.
  static void showIncomeDetailTypeModalBottomSheet(
    BuildContext context,
    ValueChanged<String?> onTap, {
    String? currentType,
  }) {
    showIncomeExpenseDetailTypeModalBottomSheet(
      context,
      IncomeExpenseDetailTypeLoader.getDetailTypes(IncomeExpenseType.income),
      onTap,
      title: '收入类别',
      currentType: currentType,
      height: 280.0,
    );
  }

  /// Shows a pick modal for expense detail type selection.
  static void showExpenseDetailTypeModalBottomSheet(
    BuildContext context,
    ValueChanged<String?> onTap, {
    String? currentType,
  }) {
    showIncomeExpenseDetailTypeModalBottomSheet(
      context,
      IncomeExpenseDetailTypeLoader.getDetailTypes(IncomeExpenseType.expense),
      onTap,
      title: '支出类别',
      currentType: currentType,
    );
  }

  /// Shows a pick modal for payment type selection.
  static void showPaymentTypeModalBottomSheet(
    BuildContext context,
    ValueChanged<String> onTap, {
    String? currentType,
  }) {
    showTypeModalBottomSheet(
      context,
      PaymentType.getCategories(),
      onTap,
      title: '收支方式',
      currentType: currentType,
      height: 170.0,
    );
  }
}

/// Builds the income/expense detail list tile.
/// [keywords] for display in highlight.
class IncomeExpenseDetailListTile extends StatelessWidget {
  const IncomeExpenseDetailListTile(
    this.item,
    this.onTap, {
    super.key,
    this.displayIncomeExpenseDate = false,
    this.keywords,
  });

  final IncomeExpenseDetail item;
  final GestureTapCallback onTap;
  final bool displayIncomeExpenseDate;
  final List<String>? keywords;

  @override
  Widget build(BuildContext context) {
    return ListTile(
      title: keywords?.isNotEmpty == true
          ? RichText(
              text: TextSpan(
                style: DefaultTextStyle.of(context).style,
                children: buildTextSpansWithKeywords(item.details!, keywords),
              ),
            )
          : Text(item.details!, style: const TextStyle(fontSize: 14.0)),
      subtitle: Text(
        _getSubtitle(),
        style: const TextStyle(fontSize: 12.0, color: Colors.black54),
      ),
      trailing: Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          if (item.bankCard?.id.isNotNullOrEmpty == true)
            BankLogo(item.bankCard!.bank!, width: 14.0),
          if (item.bankCard?.id.isNotNullOrEmpty == true)
            const SizedBox(width: 5.0),
          Align(
            alignment: Alignment.topCenter,
            child: AmountSymbol(
              item.amount!,
              size: 10.0,
              marginTop: 20.0,
              color: item.amount! > 0
                  ? Colors.black54
                  : IncomeExpenseDetailShared.expenseAmountColor,
            ),
          ),
          Text(
            formatNumber(item.amount!.abs()),
            style: TextStyle(
              fontSize: 16.0,
              color: item.amount! > 0
                  ? Colors.black54
                  : IncomeExpenseDetailShared.expenseAmountColor,
            ),
          ),
        ],
      ),
      onTap: onTap,
    );
  }

  String _getSubtitle() {
    var subtitle = IncomeExpenseDetailShared.getIncomeOrExpenseTypeTitle(item);

    if (displayIncomeExpenseDate) {
      subtitle +=
          ' @ ${item.incomeExpenseDate!.convertDateToFriendlyText(DatePatterns.longDate)}';
    }

    return subtitle;
  }
}

class AmountSymbol extends StatelessWidget {
  const AmountSymbol(
    this.amount, {
    super.key,
    this.size,
    this.marginTop = 5.0,
    this.color = Colors.black45,
  });

  final double amount;
  final double? size;
  final double marginTop;
  final Color? color;

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.only(top: marginTop),
      child: amount >= 0
          ? Icon(MdiIcons.plus, color: color, size: size)
          : Icon(MdiIcons.minus, color: color, size: size),
    );
  }
}
